import random
import time
from datetime import datetime, timedelta
from database import Mysql
import conf
from utils import adjust_time

# 工单时间参数 (小时)
random_0_300s = random.randint(0, 300) * 1000  # 0-300秒

def update_prod(db):
    # 获取当前毫秒级时间戳（替代UNIX_TIMESTAMP() * 1000）
    current_timestamp = int(time.time() * 1000)

    # 1、更新mes_task_master表，
    # 设置plan_start_time、plan_end_time、actual_start_time、actual_end_time、bill_time、create_time（基于sale_order的audit_time）
    sql1 = """
        SELECT mt.id, so.order_code, so.order_time, so.audit_time 
        FROM mes_task_master mt
        JOIN sale_order so ON mt.sale_order_no = so.order_code
    """
    results = db.get_all(sql1)
    update_sql1 = """
        UPDATE mes_task_master 
        SET plan_start_time = %s, 
            plan_end_time = %s, 
            actual_start_time = %s, 
            actual_end_time = %s, 
            bill_time = %s, 
            create_time = %s 
        WHERE id = %s
    """
    if not results:
        return
    for result in results:
        id = int(result["id"])
        order_time = result["order_time"]
        audit_time = result["audit_time"]

        t = audit_time + random.randint(10 * 60 * 1000, 20 * 60 * 1000)  # 将计划开始时间设置为审核时间往后加10-20分钟
        t = adjust_time(t)
        plan_start_time = t
        plan_end_time = t + 30 * 24 * 60 * 60 * 1000  # 将计划结束时间设置为计划开始时间往后加一个月
        actual_start_time = t + random.randint(3 * 60 * 1000, 10 * 60 * 1000)  # 将实际开始时间设置为计划开始时间往后加3-10分钟
        actual_end_time = actual_start_time + random.randint(72 * 60 * 60 * 1000,
                                                             88 * 60 * 60 * 1000)  # 将实际结束时间设置为实际开始时间往后加72至88小时
        actual_start_time = adjust_time(actual_start_time)
        actual_end_time = adjust_time(actual_end_time)
        bill_time = order_time  # 将单据日期设置为订单日期
        create_time = t  # 将创建时间设置为t值

        count1 = db.update(update_sql1, (
            plan_start_time, plan_end_time, actual_start_time, actual_end_time, bill_time, create_time, id))
        if count1 > 0:
            print("UPDATE 执行成功，影响了 {} 行".format(count1))
        else:
            print("UPDATE 执行失败{} {}".format(update_sql1, (
                plan_start_time, plan_end_time, actual_start_time, actual_end_time, bill_time, create_time, id)))
            return

    # 2-1、更新生产子任务和生产工单的实际开始和实际结束时间
    update_prod_actual_time(db)

    # 2-2、更新生产子任务和生产工单的计划开始和计划结束时间
    update_prod_plan_time(db)


    # 4、生产任务异常信息处理
    # 查询需要处理的异常记录及关联的任务时间信息
    sql4 = """
        SELECT mtwore.id, mtl.actual_start_time, mtl.actual_end_time
        FROM mes_task_work_order_ex mtwore
        LEFT JOIN mes_task_line mtl ON mtwore.sub_task_id = mtl.id
        WHERE mtl.id IS NOT NULL
    """
    exception_records = db.get_all(sql4)
    count4 = 0
    
    if exception_records:
        update_sql4 = """
            UPDATE mes_task_work_order_ex
            SET create_time = %s, last_update_time = %s
            WHERE id = %s
        """
        
        for record in exception_records:
            record_id = record['id']
            actual_start = record['actual_start_time']
            actual_end = record['actual_end_time']
            
            # 仅当开始和结束时间都存在时计算随机时间
            if actual_start and actual_end and actual_end > actual_start:
                # 计算时间差并生成随机时间点（Python实现原SQL中的FLOOR(RAND() * ...)逻辑）
                time_diff = actual_end - actual_start
                random_offset = random.randint(0, time_diff)
                new_time = actual_start + random_offset
                new_time = adjust_time(new_time)
                # 执行更新
                temp_count = db.update(update_sql4, (new_time, new_time, record_id))
                count4 += temp_count
        
    print(f"SQL4 生产异常信息处理: 影响 {count4} 行")

    # 5、修改生产任务检验合规数量
    sql5 = """
        UPDATE mes_check_task_item mcti
        RIGHT JOIN mes_check_task mct ON mct.id = mcti.check_task_id
        SET mcti.ok_num = mct.check_num
        WHERE mct.wip_id != ''
    """
    count5 = db.update(sql5)
    print(f"SQL5 修改检验合规数量: 影响 {count5} 行")

    db.commit()


def update_prod_actual_time(db):
    """
    更新生产任务时间（主任务、子任务、工单）
    逻辑：
    1. 主任务实际开始时间已确定
    2. 第一个子任务实际开始时间 = 主任务实际开始时间
    3. 子任务下第一个工单实际开始时间 = 子任务实际开始时间
    4. 后续工单实际开始时间 = 上一个工单实际结束时间
    5. 工单实际结束时间 = 实际开始时间 + (plan_time + total_time ± 30分钟)
    6. 子任务实际结束时间 = 最后一个工单实际结束时间
    7. 主任务实际结束时间 = 最后一个子任务实际结束时间
    """
    try:
        # 1. 获取所有需要处理的主任务（有开始时间无结束时间）
        master_tasks = db.get_all("""
            SELECT id, actual_start_time 
            FROM mes_task_master 
            WHERE actual_start_time IS NOT NULL 
            ORDER BY id ASC
        """)

        for master in master_tasks:
            master_id = master['id']
            master_start = master['actual_start_time']

            # 2. 获取该主任务下的所有子任务（按创建时间排序）
            sub_tasks = db.get_all("""
                SELECT id FROM mes_task_line 
                WHERE task_id = %s 
                ORDER BY id ASC
            """, (master_id,))

            if not sub_tasks:
                continue

            prev_sub_end = None
            # 对于每个子任务
            for i, sub in enumerate(sub_tasks):
                sub_id = sub['id']

                # 3. 确定子任务实际开始时间
                sub_start = master_start if i == 0 else prev_sub_end

                # 4. 处理该子任务下的所有工单
                work_orders = db.get_all("""
                    SELECT id, item_id 
                    FROM mes_task_work_order 
                    WHERE sub_task_id = %s 
                    ORDER BY item_no ASC
                """, (sub_id,))

                if not work_orders:
                    sub_end = sub_start
                else:
                    prev_work_end = None

                    for j, work in enumerate(work_orders):
                        work_order_id = work['id']
                        item_id = work['item_id']

                        # 5. 确定工单实际开始时间
                        work_start = sub_start if j == 0 else prev_work_end

                        # 6. 计算工单时间跨度（plan_time + total_time ±30分钟）
                        time_info = db.get_all("""
                            SELECT plan_time, total_time 
                            FROM mes_routing_item 
                            WHERE id = %s
                        """, (item_id,))[0]

                        time_span = time_info['total_time']
                        random_offset = random.randint(-30 * 60 * 1000, 30 * 60 * 1000)  # ±30分钟
                        actual_span = time_span * 60 * 60 * 1000 + random_offset

                        # 7. 计算工单实际结束时间（这里目前先是过程加班最后一天不加班的逻辑，需要调整为全部加班以及全部不加班的逻辑）
                        # 如果加班
                        if conf.is_over_time:
                            work_end = work_start + actual_span
                        # 如果不加班
                        else:
                            actual_span_day = actual_span // (9 * 60 * 60 * 1000)
                            actual_span_hour = actual_span % (9 * 60 * 60 * 1000)
                            work_end_tmp = work_start + actual_span_day * 24 * 60 * 60 * 1000
                            work_end = work_end_tmp + actual_span_hour
                            work_end = adjust_time(work_end)

                        actual_work_hour = (work_end - work_start) / (1000 * 60 * 60)

                        # 8. 更新工单时间
                        db.update("""
                            UPDATE mes_task_work_order 
                            SET actual_start_time = %s, 
                                actual_end_time = %s,
                                actual_working_hour = %s
                            WHERE id = %s
                        """, (work_start, work_end, actual_work_hour, work_order_id))

                        prev_work_end = work_end

                    sub_end = prev_work_end

                prev_sub_end = sub_end

                # 9. 更新子任务时间
                db.update("""
                    UPDATE mes_task_line 
                    SET actual_start_time = %s, 
                        actual_end_time = %s 
                    WHERE id = %s
                """, (sub_start, sub_end, sub_id))

                # 10. 如果是最后一个子任务，更新主任务结束时间
                if i == len(sub_tasks) - 1:
                    db.update("""
                        UPDATE mes_task_master 
                        SET actual_end_time = %s 
                        WHERE id = %s
                    """, (sub_end, master_id))

        db.commit()
        print("生产任务实际时间更新完成")

    except Exception as e:
        db.rollback()
        print(f"更新生产任务实际时间失败: {str(e)}")
        raise


def update_prod_plan_time(db):
    # 获取当前毫秒级时间戳（替代UNIX_TIMESTAMP() * 1000）
    current_timestamp = int(time.time() * 1000)
    """
    更新所有主任务下属子任务、工单的计划时间
    """
    try:
        sql1 = """
            UPDATE mes_task_line mtl
            JOIN mes_task_master mtm ON mtl.task_id = mtm.id
            SET
                mtl.plan_start_time = mtm.plan_start_time,
                mtl.plan_end_time = mtm.plan_end_time,
                mtl.last_update_time = %s  # 使用Python生成的当前时间戳
            WHERE
                mtl.task_id IS NOT NULL
        """
        count1 = db.update(sql1, (current_timestamp,))
        print(f"SQL1 同步生产子任务时间: 影响 {count1} 行")

        sql2 = """
            UPDATE mes_task_work_order st
            JOIN mes_task_line t ON st.sub_task_id = t.id
            SET 
                st.plan_start_time = t.plan_start_time,
                st.plan_end_time = t.plan_end_time
        """
        count2 = db.update(sql2)
        print(f"SQL2 同步生产工单时间: 影响 {count2} 行")

        db.commit()
        print("所有主任务下的子任务和工单计划时间已更新完成")

    except Exception as e:
        db.rollback()
        print(f"批量更新失败: {str(e)}")
        raise


if __name__ == "__main__":
    python_timestamp = int(time.time())
    print(f"Python生成的毫秒级时间戳: {python_timestamp}")
        
    


